package socket;

import javax.xml.ws.handler.Handler;
import java.io.*;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;

/**
 * 聊天室客户端
 */
public class Client {
    /*
        java.net.Socket 套接字
        Socket封装了TCP协议的通讯细节，使用它可以通过网络与远端计算机进行TCP链接
        并基于两条流(输入与输出)与远端计算机通讯。
        Socket可以想象为我们使用的"手机"。
     */
    private Socket socket;
    private String name = "duzhihua";

    public Socket getSocket() {
        return socket;
    }

    public void setSocket(Socket socket) {
        this.socket = socket;
    }

    public String getName() {
        return name;
    }

    /**
     * 构造器，用来初始化客户端
     */
    public Client() {
        try {
            /*
            实例化Socket时需要传入两个参数用于与远端计算机建立链接
            实例化的过程就是与远端计算机建立链接的过程。
            如果实例化成功说明与远端计算机建立链接。
            如果建立链接失败则会抛出异常
            参数1:远端计算机的IP地址
            参数2:远端计算机上的服务端程序开启的服务端口
                 我们通过IP可以找到网络上服务端所在的计算机，
                 通过端口找到该计算机上运行的服务端应用程序
                 注:localhost代表本机
         */
            System.out.println("正在链接服务端...");
            socket = new Socket("localhost", 8088);
            System.out.println("与服务端链接成功!!!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 客户端开始工作的方法
     */
    public void start() {
        try {
            /*
                Socket提供的重要方法
                OutputStream getOutputStream()
                通过socket获取的字节输出流写出的数据就会发送给与之连接的远端计算机。
             */
            //先启动线程用于读取服务端发送过来的消息
            ServerHandler serverHandler = new ServerHandler();
            Thread t = new Thread(serverHandler);
            t.setDaemon(true);
            t.start();

            OutputStream out = socket.getOutputStream();
            OutputStreamWriter osw = new OutputStreamWriter(out, StandardCharsets.UTF_8);
            BufferedWriter bw = new BufferedWriter(osw);
            PrintWriter pw = new PrintWriter(bw, true);

            Scanner scanner = new Scanner(System.in);
            System.out.print("请输入发送信息内容（输入exit退出）:");
            while (true) {
                String line = scanner.nextLine();//获取控制台输入的一行字符串
                if ("exit".equalsIgnoreCase(line)) {
                    break;
                }
                pw.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //最终交互完毕后要断开连接
            try {
                //close方法内部会进行TCP的四次挥手操作
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    public static void main(String[] args) {
        Client client = new Client();
        client.start();
    }

    /**
     * 该线程负责读取来自服务端发送过来的消息
     */
    private class ServerHandler implements Runnable {
        public void run() {
            try {
                InputStream in = socket.getInputStream();
                InputStreamReader isr = new InputStreamReader(in);
                BufferedReader br = new BufferedReader(isr);

                String line;
                while ((line = br.readLine()) != null) {
                    System.out.println(line);
                }

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
